home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / rootcheck / rootcheck.c < prev   
Encoding:
C/C++ Source or Header  |  1998-08-13  |  6.6 KB  |  315 lines

  1. /*
  2.    BiT '98
  3.    completely rewritten for obvious reasons...
  4.    first of all, it didnt work (sigsegv and shit)
  5.    second.. my house got raided and everything was taken
  6.    third.. i have nothing to do waiting for my phone line to return.......
  7.  */
  8.  
  9. /*
  10.    Killing processes with (e)uid==0 if they aint owned by root or anyone
  11.    in /etc/rootusers, except if the process name is in /etc/suids
  12.    
  13.    bugfix: forgot a signal() in the SIGHUP handler, im to lazy to use 
  14.         sigaction()
  15.  */
  16.  
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <sys/types.h>
  20. #include <sys/socket.h>
  21. #include <sys/stat.h>
  22. #include <netdb.h>
  23. #include <fcntl.h>
  24. #include <unistd.h>
  25. #include <dirent.h>
  26. #include <signal.h>
  27. #include <pwd.h>
  28. #include <time.h>
  29.  
  30. #define VERSION     "0.6"
  31. #define ROOTUSERS    "/etc/rootusers"
  32. #define SUIDS        "/etc/suids"
  33. #define PIDFILE        "/var/run/rootcheck.pid"
  34. #define EMAIL        "bit@localhost" /* you might want to change this */
  35. #define NETSTAT     "/bin/netstat"
  36. #define W         "/usr/bin/w"
  37. #define LAST        "/usr/bin/last"
  38.  
  39. struct rootcheck {
  40.     char name[256];
  41.     pid_t pid, ppid;
  42.     uid_t uid, euid;
  43. };
  44.  
  45. uid_t rootusers[16];        /* more then 16 roots?! */
  46. char suids[64][256];        /* what about removing some root suids? */
  47. int nrootusers, nsuids;
  48.  
  49. void sighup(int s);
  50. void rehash(int status);
  51. int okuid(uid_t uid);
  52. void foreverloop(void);
  53. struct rootcheck *getinfo(char *d_name);
  54. struct rootcheck *trace_to_init(struct rootcheck par);
  55. void checkup(char *d_name);
  56. void mail_n_kill(struct rootcheck cur, struct rootcheck par);
  57.  
  58. void main(int argc, char **argv)
  59. {
  60.     int i;
  61.     char buf[512];
  62.  
  63.     printf("rootcheck %s - BiT '98\n\n", VERSION);
  64.  
  65.     if (geteuid())
  66.     printf("I prefer euid 0\n"), exit(-1);
  67.  
  68.     if ((i = open(PIDFILE, O_RDONLY)) != -1) {
  69.     read(i, buf, sizeof(buf));
  70.     if (kill(atoi(buf), SIGCHLD) != -1)
  71.         printf("Allready running.\n"), exit(-1);
  72.     close(i);
  73.     }
  74.     printf("Loading init files...");
  75.     rehash(0);
  76.     printf("done\nSetting up HUP handler and detaching...");
  77.     fflush(stdout);
  78.  
  79.     signal(SIGHUP, (void *) &sighup);
  80.     if ((i = fork()) == -1)
  81.     printf("can't fork()?!\n"), exit(-1);
  82.     if (i)
  83.     putchar('\n'), close(0), close(1), close(2), exit(-1);
  84.  
  85.     if ((i = open(PIDFILE, O_WRONLY | O_CREAT)) != -1) {
  86.     sprintf(buf, "%d", getpid());
  87.     write(i, buf, strlen(buf));
  88.     close(i);
  89.     }
  90.     foreverloop();
  91. }
  92.  
  93. void foreverloop(void)
  94. {
  95.     DIR *procdir;
  96.     struct dirent *pproc;
  97.     struct stat sbuf;
  98.     chdir("/proc");
  99.     procdir = opendir(".");    /* if this doesnt work............ */
  100.  
  101.     while (1) {
  102.     if ((pproc = readdir(procdir)) != NULL) {
  103.         if (stat(pproc->d_name, &sbuf) == -1)
  104.         continue;
  105.         if (S_ISDIR(sbuf.st_mode))
  106.         checkup(pproc->d_name);
  107.     } else
  108.         rewinddir(procdir);
  109.     usleep(10);        /* yaya lemme eat yer cpu */
  110.     }
  111. }
  112.  
  113. void checkup(char *d_name)
  114. {
  115.     struct rootcheck *p, cur, par;
  116.     char buf[512];
  117.  
  118.     if (!strcmp(d_name, "scsi") || !strcmp(d_name, "net") || !strcmp(d_name, "sys")
  119.     || !strcmp(d_name, "self") || !strcmp(d_name, ".")
  120.     || !strcmp(d_name, "..") || !strcmp(d_name, "1"))
  121.     return;
  122.  
  123.  
  124.     if ((p = getinfo(d_name)) == NULL)
  125.     return;
  126.     memcpy(&cur, p, sizeof(struct rootcheck));
  127.  
  128.     if (cur.ppid == 1)
  129.     return;
  130.  
  131.     if (cur.uid && cur.euid)
  132.     return;
  133.  
  134.     if (oksuid(cur.name))
  135.     return;
  136.  
  137.     if ((p = trace_to_init(cur)) == NULL)
  138.     return;
  139.     memcpy(&par, p, sizeof(struct rootcheck));
  140.  
  141.     if (okuid(par.uid))
  142.     return;
  143.  
  144.     mail_n_kill(cur, par);
  145. }
  146.  
  147. void mail_n_kill(struct rootcheck cur, struct rootcheck par)
  148. {
  149.     FILE *fd;
  150.     char buf[256], fn[256];
  151.     struct passwd *pwd;
  152.  
  153.     unsetenv("IFS");
  154.     srand(time(NULL));
  155.     pwd = getpwuid(par.uid);
  156.     sprintf(fn, "/tmp/rc%d", rand());
  157.  
  158.     fd = fopen(fn, "w");
  159.     sprintf(buf, "User %s got euid 0 from %s\n\nSystem data follows:\n\n",
  160.         pwd->pw_name, cur.name);
  161.     fputs(buf, fd);
  162.     fclose(fd);
  163.  
  164.     sprintf(buf, "%s -a -n >> %s", NETSTAT, fn);
  165.     system(buf);
  166.  
  167.     sprintf(buf, "%s >> %s", W, fn);
  168.     system(buf);
  169.  
  170.     sprintf(buf, "%s -20 >> %s", LAST, fn);
  171.     system(buf);
  172.  
  173.     sprintf(buf, "cat %s | mail %s", fn, EMAIL);
  174.     system(buf);
  175.  
  176.     unlink(fn);
  177.     kill(par.pid, 9);        /* SPLAM! */
  178. }
  179.  
  180. /* not really correct name, traces until parents uid is 0 */
  181.  
  182. struct rootcheck *trace_to_init(struct rootcheck par)
  183. {
  184.     static struct rootcheck *p, cur, old;
  185.     char buf[512];
  186.  
  187.     sprintf(buf, "%d", par.ppid);
  188.     if ((p = getinfo(buf)) == NULL)
  189.     return NULL;
  190.     memcpy(&old, &par, sizeof(struct rootcheck));
  191.     memcpy(&cur, p, sizeof(struct rootcheck));
  192.  
  193.     while (1) {
  194.     if (cur.uid == 0 && cur.euid == 0)
  195.         return &old;
  196.     sprintf(buf, "%d", cur.ppid);
  197.     if ((p = getinfo(buf)) == NULL)
  198.         return NULL;
  199.     memcpy(&old, &cur, sizeof(struct rootcheck));
  200.     memcpy(&cur, p, sizeof(struct rootcheck));
  201.     }
  202. }
  203.  
  204. int oksuid(char *owner)
  205. {
  206.     int i;
  207.  
  208.     for (i = 0; i < nsuids; i++)
  209.     if (strcasecmp(suids[i], owner) == 0)
  210.         return 1;
  211.     return 0;
  212. }
  213.  
  214. int okuid(uid_t uid)
  215. {
  216.     int i;
  217.  
  218.     if (!uid)
  219.     return 1;
  220.  
  221.     for (i = 0; i < nrootusers; i++) {
  222.     if (rootusers[i] == uid)
  223.         return 1;
  224.     }
  225.     return 0;
  226. }
  227.  
  228. struct rootcheck *getinfo(char *d_name)
  229. {
  230.     static struct rootcheck rc;
  231.     char buf[512], fn[512], *p, i;
  232.     FILE *fd;
  233.  
  234.     sprintf(fn, "%s/status", d_name);
  235.  
  236.     if ((fd = fopen(fn, "r")) == NULL)
  237.     return NULL;
  238.  
  239.     if (fgets(buf, sizeof(buf), fd) == NULL)
  240.     return NULL;
  241.     buf[strlen(buf) - 1] = 0;
  242.     strncpy(rc.name, (buf + 6), sizeof(rc.name));
  243.  
  244.     if (fgets(buf, sizeof(buf), fd) == NULL)
  245.     return NULL;
  246.  
  247.     if (fgets(buf, sizeof(buf), fd) == NULL)
  248.     return NULL;
  249.     rc.pid = atoi((buf + 5));
  250.  
  251.     if (fgets(buf, sizeof(buf), fd) == NULL)
  252.     return NULL;
  253.     rc.ppid = atoi((buf + 6));
  254.  
  255.     if (fgets(buf, sizeof(buf), fd) == NULL)
  256.     return NULL;
  257.  
  258.     p = buf + 5;
  259.     for (i = 0; *(p + i) != '\t'; i++);
  260.     *(p + i) = 0;
  261.     rc.uid = atoi(p);
  262.  
  263.     p += i;
  264.     p++;
  265.     for (i = 0; *(p + i) != '\t'; i++);
  266.     *(p + i) = 0;
  267.     rc.euid = atoi(p);
  268.     fclose(fd);
  269.  
  270.     return &rc;
  271. }
  272.  
  273. void sighup(int s)
  274. {
  275.     signal(SIGHUP, (void *) &sighup);
  276.     rehash(1);
  277. }
  278.  
  279. void rehash(int status)
  280. {
  281.     FILE *fd;
  282.     char buf[256];
  283.     struct passwd *pwd;
  284.  
  285.     nsuids = nrootusers = 0;
  286.  
  287.     fd = fopen(ROOTUSERS, "r");
  288.     if (fd == NULL && !status)
  289.     printf("can't open %s..", ROOTUSERS);
  290.  
  291.     if (fd) {
  292.     while (fgets(buf, sizeof(buf), fd) != NULL) {
  293.         if (buf[strlen(buf) - 1] == '\n')
  294.         buf[strlen(buf) - 1] = 0;
  295.         if ((pwd = getpwnam(buf)) == NULL)
  296.         break;
  297.         rootusers[nrootusers++] = pwd->pw_uid;
  298.     }
  299.     fclose(fd);
  300.     }
  301.     fd = fopen(SUIDS, "r");
  302.     if (fd == NULL && !status)
  303.     printf("can't open %s..", SUIDS);
  304.  
  305.     if (fd) {
  306.     while (fgets(buf, sizeof(buf), fd) != NULL) {
  307.         if (buf[strlen(buf) - 1] == '\n')
  308.         buf[strlen(buf) - 1] = 0;
  309.         buf[255] = 0;
  310.         strcpy(suids[nsuids++], buf);
  311.     }
  312.     fclose(fd);
  313.     }
  314. }
  315.